// 通过compile对模板进行解析，在解析的过程中会分析指令，并生成订阅者（函数，订阅的数据发生更改后要更新视图）
// 数据与订阅者的关系 是一对多的（一个数据对应着多个订阅者，比如str对应着三个订阅者）
function Yuma(config) {
	// 挂载的DOM元素对象
	this.$el = document.querySelector(config.el);
	// 将配置对象中的data作为实例属性$data的值
	this.$data = config.data;
	// 设置实例属性binds,数据的结构与$data的结构相同
	this.binds = {};
	this.observer();
	// 调用解析器
	this.compile();
}

Object.assign(Yuma.prototype, {
	// 观察者：观察数据是否发生改变，一旦发生改变就要通知订阅者，订阅者负责更新元素中的属性值。
	// 数据发生改变那么要让对应模板中的元素属性值也要发生改变！
	// 每一个数据有可能对着多个元素！
	// 数据可能有多个，每一个又有可能对应着多个元素！
	observer() {
		for (let key in this.$data) {
			this.binds[key] = [];// 设置实例属性binds,数据的结构与$data的结构相同
			Object.defineProperty(this, key, {
				get() {
					return this.$data[key]
				},
				set(v) {
					this.$data[key] = v;
					// 如何知道要更改哪些元素的属性值
					this.binds[key].forEach(update=>update(v))
				}
			})
		}
	},
	// 解析器：是对模板进行解析（指令，过滤器，模板字符串等）
	compile() {
		for (let i = 0; i < this.$el.children.length; i++) {
			const node = this.$el.children[i];// 要解析的元素节点。
			// 该元素是否使用了指令y-model
			if (node.hasAttribute("y-model")) {
				const attrValue = node.getAttribute("y-model");
				// 1- 设置value值
				node.value = this[attrValue];
				// 2- 增加事件
				node.addEventListener("input", (e) => {
					this[attrValue] = e.target.value;
				})
				// 3- 数据一旦发生更改，node元素下的value值要与数据同步
				this.binds[attrValue].push(v => {
					node.value = v;
				})
				
			}
			if (node.hasAttribute("y-html")) {
				node.innerHTML = this[node.getAttribute("y-html")];
				
				// 如果数据一旦发生更改，node元素下的innerHTML值要与数据同步
				const attrValue = node.getAttribute("y-html");
				this.binds[attrValue].push(v => {
					node.innerHTML = v;
				})
			}
			if (node.hasAttribute("y-text")) {
				node.innerText = this[node.getAttribute("y-text")];
				// 如果数据一旦发生更改，node元素下的innerText值要与数据同步
				const attrValue = node.getAttribute("y-text");
				this.binds[attrValue].push(v => {
					node.innerText = v;
				})
			}
		}
	}
	
	
})

